/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2010.

	This file is part of Maxsi Engine.

	Maxsi Engine is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi engine is distributed in the hope that it will be useful, but WITHOUT
	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
	FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
	for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Engine. If not, see <http://www.gnu.org/licenses/>.

	MaxsiEngine.dll
	A general purpose C++ library for the Maxsi Technology Project.

	MaxsiCRuntime.cpp
	Turns out MinGW/GCC doesn't support as much useful stuff as Microsoft, so
	we have to implement it ourselves!

******************************************************************************/
#include "MaxsiEngine.h"

#ifdef __GNUC__

BeginMaxsiNamespace

int strcat_s(char* strDestination, size_t numberOfElements, const char* strSource)
{
	if ( strlen(strDestination) + strlen(strSource) +1 > numberOfElements )
	{
		// We should throw a warning here! For now, just crash
		char* DeletingThisWillMakeAHorribleCrash = "Yay!";
		delete[] DeletingThisWillMakeAHorribleCrash;

		MAXSI_TODO("Add an assertion here!");

		return 0;
	} 

	strcat(strDestination, strSource);

	return 1;
}

int wcscat_s(wchar_t* strDestination, size_t numberOfElements, const wchar_t* strSource)
{
	if ( wcslen(strDestination) + wcslen(strSource) +1 > numberOfElements )
	{
		// We should throw a warning here! For now, just crash
		wchar_t* DeletingThisWillMakeAHorribleCrash = L"Yay!";
		delete[] DeletingThisWillMakeAHorribleCrash;

		MAXSI_TODO("Add an assertion here!");

		return 0;
	} 

	wcscat(strDestination, strSource);

	return 1;
}

int strcpy_s(char* strDestination, size_t numberOfElements, const char* strSource)
{
	if ( strlen(strSource) + 1 < numberOfElements )
	{
		strcpy(strDestination, strSource);
		return 1;
	}
	else
	{
		return 0;
	}
}

int wcscpy_s(wchar_t* strDestination, size_t numberOfElements, const wchar_t* strSource)
{
	if ( wcslen(strSource) + 1 < numberOfElements )
	{
		wcscpy(strDestination, strSource);
		return 1;
	}
	else
	{
		return 0;
	}
}

#if 0 // Replaced by Maxsi::PrintString

int	_itoa_s(int value, char *buffer, size_t sizeInCharacters, int radix)
{
	if ( radix == 10 )
	{
		snprintf(buffer, sizeInCharacters, "%i", value);
	}
	else if  ( radix == 16 )
	{
		snprintf(buffer, sizeInCharacters, "%X", value);
	}
	else
	{
		return 0;
	}
	return 1;
}

int	_itow_s(int value, wchar_t *buffer, size_t sizeInCharacters, int radix)
{
	if ( radix == 10 )
	{
		swprintf(buffer, sizeInCharacters, L"%i", value);
	}
	else if  ( radix == 16 )
	{
		swprintf(buffer, sizeInCharacters, L"%X", value);
	}
	else
	{
		return 0;
	}
	return 1;
}


int	_uitow_s(int value, wchar_t *buffer, size_t sizeInCharacters, int radix)
{
	if ( radix == 10 )
	{
		swprintf(buffer, sizeInCharacters, L"%u", value);
	}
	else if  ( radix == 16 )
	{
		swprintf(buffer, sizeInCharacters, L"%X", value);
	}
	else
	{
		return 0;
	}
	return 1;
}

int	_i64toa_s(int64_t value, char *buffer, size_t sizeInCharacters, int radix)
{
	if ( radix == 10 )
	{
#ifdef __MINGW_H
		snprintf(buffer, sizeInCharacters, "%I64d", value);
#else
		snprintf(buffer, sizeInCharacters, "%lld", (long long)value);
#endif
	}
	else if  ( radix == 16 )
	{
#ifdef __MINGW_H
		snprintf(buffer, sizeInCharacters, "%I64X", value);
#else
		snprintf(buffer, sizeInCharacters, "%llX", (long long)value);
#endif
	}
	else
	{
		return 0;
	}
	return 1;
}

int	_i64tow_s(int64_t value, wchar_t *buffer, size_t sizeInCharacters, int radix)
{
	if ( radix == 10 )
	{
#ifdef __MINGW_H
		swprintf(buffer, sizeInCharacters, L"%I64d", value);
#else
		swprintf(buffer, sizeInCharacters, L"%lld", (long long)value);
#endif
	}
	else if  ( radix == 16 )
	{
#ifdef __MINGW_H
		swprintf(buffer, sizeInCharacters, L"%I64X", value);
#else
		swprintf(buffer, sizeInCharacters, L"%llX", (long long)value);
#endif
	}
	else
	{
		return 0;
	}
	return 1;
}

int	_ui64toa_s(uint64_t value, char *buffer, size_t sizeInCharacters, int radix)
{
	if ( radix == 10 )
	{
#ifdef __MINGW_H
		snprintf(buffer, sizeInCharacters, "%I64u", value);
#else
		snprintf(buffer, sizeInCharacters, "%llu", (unsigned long long)value);
#endif
	}
	else if  ( radix == 16 )
	{
#ifdef __MINGW_H
		snprintf(buffer, sizeInCharacters, "%I64X", value);
#else
		snprintf(buffer, sizeInCharacters, "%llX", (unsigned long long)value);
#endif
	}
	else
	{
		return 0;
	}
	return 1;
}

int	_ui64tow_s(uint64_t value, wchar_t *buffer, size_t sizeInCharacters, int radix)
{
	if ( radix == 10 )
	{
#ifdef __MINGW_H
		swprintf(buffer, sizeInCharacters, L"%I64u", value);
#else
		swprintf(buffer, sizeInCharacters, L"%llu", (unsigned long long)value);
#endif
	}
	else if  ( radix == 16 )
	{
#ifdef __MINGW_H
		swprintf(buffer, sizeInCharacters, L"%I64X", value);
#else
		swprintf(buffer, sizeInCharacters, L"%llX", (unsigned long long)value);
#endif
	}
	else
	{
		return 0;
	}
	return 1;
}

int _gcvt_s(char *buffer, size_t sizeInBytes, double value, int digits )
{
#ifdef __MINGW_H
	sprintf(buffer, "%.*g", sizeInBytes, value);
#else
	snprintf(buffer, sizeInBytes, "%.*g", digits, value);
#endif
	
	return 1;
}

#endif

#if 0
#ifdef __MINGW_H // __time64_t seems to create problems on Linux
errno_t _gmtime64_s(tm* _tm, const __time64_t* time)
{
	tm*	Result	=	_gmtime64(time);
	memcpy(_tm, Result, sizeof(tm));
	return 0;
}
#endif
#endif

errno_t asctime_s(char* buffer, size_t numberOfElements, const struct tm *_tm)
{
	char* Time = asctime(_tm);

	if ( strlen(Time) + 1 > numberOfElements ) { return 1; }

	memcpy(buffer, Time, strlen(Time) + 1);

	return 0;
}

errno_t _get_errno(int * _Value)
{
	*_Value = errno;
	return 0;
}

EndMaxsiNamespace

#endif
